package com.gsafety.libraryktx

import com.google.gson.Gson
import kotlinx.coroutines.*
import retrofit2.Call
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 启动一个协程
 */
inline fun launch(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        noinline block: suspend CoroutineScope.() -> Unit
): Job?
{
    return try
    {
        GlobalScope.launch(context, start, block)
    } catch (e: Exception)
    {
        e.printStackTrace()
        null
    }
}

/**
 * 协程里的暂停
 */
suspend inline fun delay(timeMillis: Long)
{
    kotlinx.coroutines.delay(timeMillis)
}

/**
 * 协程丶同步
 */
fun <T> async(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        block: suspend CoroutineScope.() -> T

) = GlobalScope.async(context, start, block)


/**
 * 网络请求处理
 */
suspend fun <T> execute(
    call: Call<T>,
    onSuccess: ((result: T) -> Unit)? = null,
    onFinally: (() -> Unit)? = null,
    onFail: ((t: Throwable?) -> Unit)? = null
) = withContext(IO)
{
    try
    {
        val response = call.execute()
        if (response.isSuccessful)
        {
            val body = response.body()
            if (body != null)
            {
                if (onSuccess != null)
                {
                    launch (UI) {
                        onSuccess.invoke(body)
                    }
                }
            } else
            {
                if (onFail != null)
                {
                    launch(UI) {
                        onFail.invoke(java.lang.Exception("response.body() == NULL"))
                    }
                }

            }
        } else
        {
            if (onFail != null)
            {
                launch(UI) {
                    onFail.invoke(java.lang.Exception(response.message()))
                }
            }
        }
    } catch (e: java.lang.Exception)
    {
        e.printStackTrace()
        if (onFail != null)
        {
            launch(UI) {
                onFail.invoke(e)
            }
        }

    } finally
    {
        if (onFinally != null)
        {
            launch(UI) {
                onFinally.invoke()
            }
        }
    }
}
/**
 * 各大环境
 */
inline val UI get() = Dispatchers.Main
inline val Default get() = Dispatchers.Default
inline val IO get() = Dispatchers.IO
inline val Unconfined get() = Dispatchers.Unconfined


val gson by lazy { Gson() }
